﻿using Ordering.Domain.Events;
using Ordering.Domain.Exceptions;
using Ordering.Domain.Seedwork;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;

namespace Ordering.Domain.AggregatesModel.OrderAggregate
{
    public class Order
        : Entity, IAggregateRoot
    {
        /// <summary>
        /// 订单号
        /// </summary>
        public string OrderNO { get; set; }
        /// <summary>
        /// 订单类别(0:扔垃圾 1：取快递)
        /// </summary>
        public int OrderType { get; private set; }
        /// <summary>
        /// 订单创建时间
        /// </summary>
        public DateTime CreateTime { get; private set; }
        /// <summary>
        /// 修改时间
        /// </summary>
        public DateTime? UpdateTime { get; private set; }
        /// <summary>
        /// 预约时间
        /// </summary>
        public DateTime AppointmentTime { get;private set; }
        /// <summary>
        /// 地址
        /// </summary>
        public Address Address { get; private set; }
        /// <summary>
        /// 客户编码
        /// </summary>
        public string CustomerCode{ get; private set; }
        /// <summary>
        /// 订单状态
        /// </summary>
        public int OrderStatusId { get; private set; }

        public OrderStatus OrderStatus { get; private set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }

        private bool _isDraft;

        private readonly List<OrderItem> _orderItemItems;
        public IReadOnlyCollection<OrderItem> OrderItems => _orderItemItems;


        public static Order NewDraft()
        {
            var order = new Order();
            order._isDraft = true;
            return order;
        }

        protected Order()
        {
            _orderItemItems = new List<OrderItem>();
            _isDraft = false;
        }

        public Order(string customerCode,DateTime appointmentTime,int orderType,string description,string remark, Address address) : this()
        {
            this.CustomerCode = customerCode;
            this.AppointmentTime = appointmentTime;
            this.Address = address;
            this.OrderType = orderType;
            this.OrderStatusId = OrderStatus.Submitted.Id;
            this.Description = description;
            this.Remark = remark;
            this.CreateTime = DateTime.Now;
            this.OrderNO = CreateOrderNO(customerCode);
        }
        /// <summary>
        /// 新增订单明细
        /// </summary>
        /// <param name="productCode">产品代码</param>
        /// <param name="productPrice">价格</param>
        /// <param name="productName">名称</param>
        /// <param name="num">数量</param>
        /// <param name="extendField">扩展字段（快递类型:取件码）</param>
        /// <param name="remarks">备注</param>
        public void AddOrderItem(string productCode,decimal productPrice,string productName,int num,string extendField,string remarks)
        {
            OrderItem orderItem = null;
            if (this.OrderType == (int)OrderTypeEnum.Express)
            {
                if (string.IsNullOrEmpty(extendField))
                    throw new Exception("取件码不能为空");
                orderItem = new OrderItem(productCode, productPrice, productName, 1, extendField, remarks);
            }
            else
            {
                orderItem = new OrderItem(productCode, productPrice, productName, num, null, remarks);
            }
            _orderItemItems.Add(orderItem);
        }
        /// <summary>
        /// 支付订单
        /// </summary>
        public void SetPaidStatus()
        {
            if (this.OrderStatusId == OrderStatus.Submitted.Id)
            {
                this.OrderStatusId = OrderStatus.Paid.Id;
                this.Description = "The payment was performed at a simulated";

                AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems));
            }
        }
        /// <summary>
        /// 取消订单
        /// </summary>
        public void SetCancelledStatus()
        {
            if (this.OrderStatusId == OrderStatus.Paid.Id ||
                this.OrderStatusId == OrderStatus.Delivery.Id)
            {
                StatusChangeException(OrderStatus.Cancelled);
            }

            this.OrderStatusId = OrderStatus.Cancelled.Id;
            this.Description = $"The order was cancelled.";
            //AddDomainEvent(new OrderCancelledDomainEvent(this));
        }
        /// <summary>
        /// 接收订单
        /// </summary>
        public void SetReceivedStatus()
        {
            if (this.OrderStatusId != OrderStatus.Paid.Id)
            {
                StatusChangeException(OrderStatus.ReceiveConfirmed);
            }

            this.OrderStatusId = OrderStatus.ReceiveConfirmed.Id;
            this.Description = $"The order was ReceiveConfirmed.";
        }
        /// <summary>
        /// 客户下单
        /// </summary>
        /// <param name="customerCode"></param>
        private void SubmitOrderDomainEvent(string customerCode)
        {
            //var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, userName, cardTypeId,
            //                                                          cardNumber, cardSecurityNumber,
            //                                                          cardHolderName, cardExpiration);
            //this.AddDomainEvent(orderStartedDomainEvent);
        }
        /// <summary>
        /// 获取订单总价
        /// </summary>
        /// <returns></returns>
        public decimal GetOrderTotalCost()
        {
            if(this._orderItemItems.Any())
            {
                return this._orderItemItems.Sum(t => t.ProductPrice * t.Num);
            }
            else
            {
                return 0;
            }

        }
        private void StatusChangeException(OrderStatus orderStatusToChange)
        {
            throw new OrderingDomainException($"Is not possible to change the order status from {this.OrderStatusId} to {orderStatusToChange.Name}.");
        }
        private string CreateOrderNO(string customerCode)
        {
            string dateCode = DateTime.Now.ToString("yyyyMMddHHmmss");
            string orderType = this.OrderType == (int)OrderTypeEnum.Express ? "E" : "G";
            Random rom = new Random();
            char[] allcheckRandom ={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
            int randomLength = allcheckRandom.Length;
            string randomStr = string.Empty;
            for(int i = 0; i < 4;i++)
            {
                int index = rom.Next(0, randomLength);
                randomStr += allcheckRandom[index];
            }
            return $"{orderType}{dateCode}-{randomStr}";
        }
    }
}
